package cn.hxzy.controller;


import cn.hxzy.common.Result;
import cn.hxzy.common.util.OrderUtil;
import cn.hxzy.common.util.RandomId;
import cn.hxzy.entity.carteam.VehicleInformation;
import cn.hxzy.entity.order.LoaderUnloadLog;
import cn.hxzy.entity.order.RunRoute;
import cn.hxzy.entity.order.Waybill;
import cn.hxzy.entity.order.WaybillLog;
import cn.hxzy.entity.order.vo.OrderVo;
import cn.hxzy.entity.order.vo.SelectVo;
import cn.hxzy.entity.siteEntity.Site;
import cn.hxzy.erweima.service.QRService;
import cn.hxzy.feign.clients.DriverCarClient;
import cn.hxzy.feign.clients.SiteClient;
import cn.hxzy.feign.clients.SourceListClient;
import cn.hxzy.service.LoaderUnloadLogService;
import cn.hxzy.service.RunRouteService;
import cn.hxzy.service.WaybillLogService;
import cn.hxzy.service.WaybillService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.seata.spring.annotation.GlobalTransactional;

import org.apache.ibatis.io.ResolverUtil;
import org.apiguardian.api.API;
import org.checkerframework.common.value.qual.StringVal;
import org.redisson.PubSubEntry;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hk
 * @since 2023-06-23
 */
@CrossOrigin
@RestController
@RequestMapping("/waybill")
public class WaybillController {
    @Autowired
    private WaybillService waybillService;
    @Autowired
    private Redisson redisson;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private WaybillLogService waybillLogService;
    @Autowired
    private LoaderUnloadLogService loaderUnloadLogService;
    @Autowired
    private SourceListClient sourceListClient;
    @Autowired
    private QRService qrService;
    @Autowired
    private DriverCarClient driverCarClient;
    @Autowired
    private SiteClient siteClient;
    @Autowired
    private RunRouteService runRouteService;
    @Autowired
    private ObjectMapper objectMapper;
    @GetMapping("/test")
    public void test(){
        stringRedisTemplate.opsForValue().set("HY-230684618345211",5000+"");
    }
    /**
     * 抢单
     *
     * @param orderVo
     * @return
     */
    @PostMapping("order")
    @GlobalTransactional
    public Result order(@RequestBody OrderVo orderVo) {
        System.out.println("进入抢单");
        //获取货源，扣减余量
        RLock myLock = redisson.getLock("myLock");
//        long id = Thread.currentThread().getId();
        try {
            myLock.lock(10, TimeUnit.SECONDS);
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("HY-230684618345211"));
            if (stock > 35) {
                int relStock = stock - 35;
                stringRedisTemplate.opsForValue().set("HY-230684618345211", relStock + "");
                sourceListClient.updateGoodsHeadroom((double) relStock, orderVo.getSourceId());
                sourceListClient.updateLoadingCount((double) 35, orderVo.getSourceId());
                System.out.println("抢单成功，剩余库存：" + relStock);
                //保存订单
                String s = waybillService.createWaybill(orderVo);
                //保存抢单运单日志
                waybillService.createQDWaybillLog(s);
            } else {
                System.out.println("抢单失败");
                return Result.error().message("抢单失败，库存不足");
            }
        } finally {
            myLock.unlock();
        }
        return Result.ok().message("抢单成功，请到服务台领取提货单");
    }

    /**
     * 到站打卡
     *
     * @param userId
     * @return
     */
    @GetMapping("/daKa/{userId}")
    @GlobalTransactional
    public Result daKa(@PathVariable String userId) {
        //修改日志表中打卡时间
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.eq("driver_id", userId);
        wrapper.eq("waybill_status", 102);
        Waybill one = waybillService.getOne(wrapper);
        QueryWrapper<WaybillLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("waybill_id", one.getWaybillId());
        WaybillLog one1 = waybillLogService.getOne(queryWrapper);
        one1.setClockInTime(new Date());
        boolean b = waybillLogService.updateById(one1);
        if (!b) {
            return Result.error().message("打卡失败");
        }
        return Result.ok().message("打卡成功");
    }

    /**
     * 到站装车
     *
     * @param loaderUnload
     * @return
     */
    @PostMapping("/zhuangChe/{userId}")
    @GlobalTransactional
    public Result zhuangChe(@RequestBody LoaderUnloadLog loaderUnload, @PathVariable String userId) {
        //新增一条装车日志
        loaderUnload.setId(OrderUtil.ZXrandom());
        Waybill waybill = selectByUserId(userId);
        loaderUnload.setWaybillId(waybill.getWaybillId());
        loaderUnloadLogService.save(loaderUnload);
        BigDecimal suttle = loaderUnload.getSuttle();
        //调用货源表修改货源,redis
        int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("HY-230684618345211"));
        double i = stock + 35 - suttle.intValue();
        stringRedisTemplate.opsForValue().set("stock", String.valueOf(i));
        waybillService.zhuangCheUpdate(waybill.getSourceId(), suttle, i);
        //运单与装车日志关联
        UpdateWrapper<Waybill> wrapper = new UpdateWrapper<>();
        wrapper.eq("waybill_id", loaderUnload.getWaybillId());
        wrapper.set("loading_scale_id", loaderUnload.getId());
        wrapper.set("waybill_status", 103);
        waybillService.update(wrapper);
        //修改运单日志表中的矿发时间
        UpdateWrapper<WaybillLog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("waybill_id", loaderUnload.getWaybillId());
        updateWrapper.set("mining_time", new Date());
        updateWrapper.set("loading time", new Date());
        waybillLogService.update(updateWrapper);
        return Result.ok().message("装车完毕，准备出发");
    }

    /**
     * 卸车
     *
     * @param loaderUnloadLog
     * @return
     */
    @PostMapping("/xieChe/{userId}")
    @GlobalTransactional
    public Result xieChe(@RequestBody LoaderUnloadLog loaderUnloadLog, @PathVariable String userId) {
        //查询装车磅单
        Waybill waybill = selectByUserId(userId);
        QueryWrapper<LoaderUnloadLog> wrapper = new QueryWrapper<>();
        wrapper.eq("waybill_id", waybill.getWaybillId());
        LoaderUnloadLog one = loaderUnloadLogService.getOne(wrapper);
        //新增一条卸车信息
        loaderUnloadLog.setId(OrderUtil.ZXrandom());
        loaderUnloadLogService.save(loaderUnloadLog);
        //装车磅单与卸车磅单比较
        //compareTo()方法，大于为1，小于为-1，等于为0
        int i = one.getSuttle().compareTo(loaderUnloadLog.getSuttle());
        //存放亏吨
        BigDecimal subtract1 = null;
        //存放亏吨扣得钱
        BigDecimal multiply = null;
        if (i > 0) {
            BigDecimal subtract = one.getSuttle().subtract(loaderUnloadLog.getSuttle());
            BigDecimal b1 = new BigDecimal(0.3);
            if (subtract.compareTo(b1) > 0) {
                subtract1 = subtract.subtract(b1);
                BigDecimal bigDecimal = new BigDecimal(100);
                multiply = subtract1.multiply(bigDecimal);
            }
        }
        //修改运单中的亏吨信息
        UpdateWrapper<Waybill> wrapper1 = new UpdateWrapper<>();
        wrapper1.eq("waybill_id", loaderUnloadLog.getWaybillId());
        wrapper1.set("loss_ton_information", subtract1);
        wrapper1.set("waybill_status", 103);
        waybillService.update(wrapper1);
        //修改运单日志中的卸车时间
        UpdateWrapper<WaybillLog> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("waybill_id", loaderUnloadLog.getWaybillId());
        updateWrapper.set("entry_time", new Date());
        updateWrapper.set("unloading_time", new Date());
        waybillLogService.update(updateWrapper);
        return Result.ok().message("卸车完成，可以重新接单");
    }

    /**
     * 根据运单状态，货源编号查询  该货源所有该状态的运单
     *
     * @param waybillStatus
     * @param sourceId
     * @return
     */
    @GetMapping("/waybillStatus/{waybillStatus}/{sourceId}")
    public Result selectByOrderStatus(@PathVariable int waybillStatus, @PathVariable String sourceId) {
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.eq("waybill_status", waybillStatus);
        wrapper.eq("source_id", sourceId);
        List<Waybill> list = waybillService.list(wrapper);
        return Result.ok().data1(list);
    }

    /**
     * 根据货源编号查询运单
     *
     * @param sourceId
     * @return
     */
    @GetMapping("/sourceId/{sourceId}")
    public Result selectBySourceId(@PathVariable String sourceId) {
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.eq("source_id", sourceId);
        List<Waybill> list = waybillService.list(wrapper);
        return Result.ok().data1(list);
    }

    /**
     * 根据用户编号查询未装车运单
     *
     * @param userId
     * @return
     */
    @GetMapping("/waybillByUserId/{userId}")
    public Waybill selectByUserId(@PathVariable String userId) {
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.eq("driver_id", userId);
        wrapper.eq("waybill_status", 102);
        Waybill one = waybillService.getOne(wrapper);
        return one;
    }

    /**
     * 展示跳转二维码，跳转到提货单界面
     *
     * @param driverId
     * @param response
     * @throws IOException
     */
    @GetMapping("/erweima/{driverId}")
    public void erweima(@PathVariable String driverId, HttpServletResponse response) throws IOException {
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.eq("driver_id",driverId);
        Waybill one = waybillService.getOne(wrapper);
        String text = one+"";//跳转路径
        qrService.generateStream(text, response);
    }
    //获得所有货源
    @GetMapping("/sourceListAll")
    public Result sourceListAll() {
        return sourceListClient.selectSource();
    }
    @GetMapping("/selectSource")
    public Result selectSourceByStatus(){
        return sourceListClient.selectSourceByStatus();
    }
    //多条件查询货源
    @GetMapping("/sourceListAll/{loading}/{unLoading}/{i}")
    public Result sourceListAll(@PathVariable String loading, @PathVariable String unLoading, @PathVariable int i) {
        return sourceListClient.sourceListAll(loading,unLoading,i);
    }
    /**
     * 判断当前车辆和司机是否可以抢单
     *
     */
    @GetMapping("/pDCarDriver/{userId}/{licensePlateNumber}")
    public Result pDCarDriver(@PathVariable String userId,@PathVariable String licensePlateNumber){
        QueryWrapper wrapper = new QueryWrapper<Waybill>();
        wrapper.eq("driver_id",userId);
        wrapper.ne("waybill_status",104);
        wrapper.ne("signing_status",102);
//        Result result = driverCarClient.selectById(carId);
//        VehicleInformation data1 =(VehicleInformation) result.getData1();
//        String licensePlateNumber = data1.getLicensePlateNumber();
        Waybill one = waybillService.getOne(wrapper);
        if (one==null){
            QueryWrapper<Waybill> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("license_plate_number",licensePlateNumber);
            wrapper.ne("waybill_status",104);
            wrapper.ne("signing_status",102);
            Waybill one1 = waybillService.getOne(wrapper1);
            if (one1==null){
                return Result.ok().message("司机和当前车辆均无订单可以接单");
            }
            return Result.error().message("当前车辆尚有订单未签收，请选择其他车辆");
        }
        return Result.error().message("当前司机尚有订单未签收，请先完成当前订单");
    }
    //根据用户查询用户绑定的两个车辆
    @GetMapping("/driverCar/user/{userId}")
    public Result selectByIdForCar(@PathVariable String userId){
        Result result = driverCarClient.selectByIdForCar(userId);
        return result;
    }
    //根据用户查询用户的默认车辆
    @GetMapping("/driverCar/selectOne/{userId}")
    public Result selectByIdForCar1(@PathVariable String userId){
        Result result = driverCarClient.selectByIdForCar1(userId);
        System.out.println("获取默认车辆");
        return result;
    }
    //根据货源编号查询货源
    @GetMapping("sourceList/selectSourceById/{sourceId}")
    public Result SelectSourceById(@PathVariable String sourceId){
        return sourceListClient.selectSourceById(sourceId);
    }
    //获取站点集合
    @GetMapping("/site")
    public Result siteList(){
        return siteClient.selectList();
    }
    //查询用户常跑路线
//    @GetMapping("/")
    //根据城市名多条件查询货源
    @PostMapping("/selectMoreBySiteName")
    public Result selectMoreBySiteName(@RequestBody SelectVo selectVo){
        return sourceListClient.selectMoreBySiteName(selectVo);
    }
    @GetMapping("/selectCity")
    public Result selectCity() throws JsonProcessingException {
        Result result = siteClient.selectList();
        List<Site> data1 =(List<Site>) result.getData1();
        String s = objectMapper.writeValueAsString(data1);
        List<Site> sites = objectMapper.readValue(s, new TypeReference<List<Site>>() {
            @Override
            public Type getType() {
                return super.getType();
            }
        });
        List<String> collect = sites.stream().map(site -> site.getCity()).distinct().collect(Collectors.toList());
        return Result.ok().data1(collect);
    }
    @PostMapping("/addCity")
    public Result addCity(@RequestBody RunRoute runRoute){
        runRoute.setRunId(RandomId.getRunId());
        boolean save = runRouteService.save(runRoute);
        if (!save){
            return Result.error();
        }
        return Result.ok();
    }
    @GetMapping("/selectRunRoute")
    public Result selectRunRoute(){
        List<RunRoute> list = runRouteService.list();
        return Result.ok().data1(list);
    }
    @GetMapping("/deleteRun/{runId}")
    public Result deleteRun(@PathVariable String runId){
        boolean b = runRouteService.removeById(runId);
        if (!b){
            return Result.error();
        }
        return Result.ok();
    }
    @GetMapping("runCount")
    public Result runCount(){
        int count = runRouteService.count();
        return Result.ok().data1(count);
    }
}

